import { EventEmitter } from 'events';
import { dorisConnectionManager } from '../database/connectors/DorisConnectionManager';
import { executionModel, scriptModel, connectionModel } from '../database/models';
// import { IExecution } from '../database/models/Execution';
import redisClient from '../config/redis';

export interface ExecutionTask {
  id: string;
  scriptId: string;
  connectionId: string;
  executedBy?: string;
  priority: number;
  createdAt: Date;
  timeout?: number;
  maxRetries?: number;
  retryCount?: number;
  processingStartedAt?: Date;
  enqueuedAt?: Date;
  status?: string;
}

export interface ExecutionProgress {
  executionId: string;
  status: 'queued' | 'running' | 'completed' | 'failed' | 'cancelled';
  progress: number; // 0-100
  message?: string;
  startTime?: Date;
  estimatedEndTime?: Date;
  currentStep?: string;
}

export interface ExecutionResult {
  executionId: string;
  success: boolean;
  data?: any[];
  affectedRows?: number;
  executionTime: number;
  error?: string;
  warnings?: string[];
}

export class SQLExecutionEngine extends EventEmitter {
  private static instance: SQLExecutionEngine;
  private taskQueue: ExecutionTask[] = [];
  private runningExecutions: Map<string, AbortController> = new Map();
  private maxConcurrentExecutions: number = 5;
  private isProcessing: boolean = false;
  private processingInterval: NodeJS.Timeout | null = null;
  private readonly QUEUE_PROCESS_INTERVAL = 1000; // 1秒
  private readonly DEFAULT_TIMEOUT = 300000; // 5分钟
  private readonly MAX_RETRIES = 3;

  private constructor() {
    super();
    this.startQueueProcessor();
  }

  public static getInstance(): SQLExecutionEngine {
    if (!SQLExecutionEngine.instance) {
      SQLExecutionEngine.instance = new SQLExecutionEngine();
    }
    return SQLExecutionEngine.instance;
  }

  // 提交执行任务到队列
  async submitExecution(task: Omit<ExecutionTask, 'id' | 'createdAt' | 'retryCount'>): Promise<string> {
    const executionTask: ExecutionTask = {
      ...task,
      id: `exec_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      createdAt: new Date(),
      retryCount: 0,
      timeout: task.timeout || this.DEFAULT_TIMEOUT,
      maxRetries: task.maxRetries || this.MAX_RETRIES
    };

    // 验证任务
    await this.validateExecutionTask(executionTask);

    // 添加到队列
    this.taskQueue.push(executionTask);
    this.sortQueue(); // 按优先级排序

    // 更新队列状态到Redis
    await this.updateQueueStatus();

    // 触发队列处理
    this.processQueue();

    this.emit('taskQueued', executionTask);
    return executionTask.id;
  }

  // 取消执行
  async cancelExecution(executionId: string): Promise<boolean> {
    try {
      // 检查是否在运行中
      if (this.runningExecutions.has(executionId)) {
        const abortController = this.runningExecutions.get(executionId)!;
        abortController.abort();
        this.runningExecutions.delete(executionId);
        
        // 更新数据库状态
        await executionModel.cancelExecution(executionId);
        
        // 更新进度状态
        await this.updateExecutionProgress(executionId, {
          executionId,
          status: 'cancelled',
          progress: 0,
          message: '执行已被取消'
        });

        this.emit('executionCancelled', executionId);
        return true;
      }

      // 检查是否在队列中
      const queueIndex = this.taskQueue.findIndex(task => task.id === executionId);
      if (queueIndex !== -1) {
        this.taskQueue.splice(queueIndex, 1);
        await this.updateQueueStatus();
        
        // 如果数据库中已有记录，更新状态
        const execution = await executionModel.findById(executionId);
        if (execution) {
          await executionModel.cancelExecution(executionId);
        }

        this.emit('taskRemovedFromQueue', executionId);
        return true;
      }

      return false;
    } catch (error) {
      console.error(`取消执行失败 ${executionId}:`, error);
      return false;
    }
  }

  // 获取执行进度
  async getExecutionProgress(executionId: string): Promise<ExecutionProgress | null> {
    try {
      const progressKey = `execution:progress:${executionId}`;
      const progressData = await redisClient.get(progressKey);
      
      if (progressData) {
        return JSON.parse(progressData);
      }

      // 如果Redis中没有，从数据库获取基本状态
      const execution = await executionModel.findById(executionId);
      if (execution) {
        return {
          executionId,
          status: execution.status as any,
          progress: execution.status === 'completed' ? 100 : 
                   execution.status === 'running' ? 50 : 0,
          startTime: execution.start_time
        };
      }

      return null;
    } catch (error) {
      console.error(`获取执行进度失败 ${executionId}:`, error);
      return null;
    }
  }

  // 获取队列状态
  async getQueueStatus(): Promise<{
    queueLength: number;
    runningExecutions: number;
    maxConcurrentExecutions: number;
    tasks: Array<{
      id: string;
      scriptId: string;
      connectionId: string;
      priority: number;
      createdAt: Date;
      estimatedStartTime?: Date;
    }>;
  }> {
    const tasks = this.taskQueue.map((task, index) => ({
      id: task.id,
      scriptId: task.scriptId,
      connectionId: task.connectionId,
      priority: task.priority,
      createdAt: task.createdAt,
      estimatedStartTime: this.estimateStartTime(index)
    }));

    return {
      queueLength: this.taskQueue.length,
      runningExecutions: this.runningExecutions.size,
      maxConcurrentExecutions: this.maxConcurrentExecutions,
      tasks
    };
  }

  // 设置最大并发执行数
  setMaxConcurrentExecutions(max: number): void {
    if (max > 0 && max <= 20) {
      this.maxConcurrentExecutions = max;
      this.processQueue(); // 重新处理队列
    }
  }

  // 获取运行中的执行列表
  getRunningExecutions(): string[] {
    return Array.from(this.runningExecutions.keys());
  }

  // 清空队列
  async clearQueue(): Promise<void> {
    this.taskQueue = [];
    await this.updateQueueStatus();
    this.emit('queueCleared');
  }

  // 暂停队列处理
  pauseQueue(): void {
    this.isProcessing = false;
    if (this.processingInterval) {
      clearInterval(this.processingInterval);
      this.processingInterval = null;
    }
    this.emit('queuePaused');
  }

  // 恢复队列处理
  resumeQueue(): void {
    if (!this.isProcessing) {
      this.startQueueProcessor();
      this.emit('queueResumed');
    }
  }

  // 启动队列处理器
  private startQueueProcessor(): void {
    this.isProcessing = true;
    this.processingInterval = setInterval(() => {
      this.processQueue();
    }, this.QUEUE_PROCESS_INTERVAL);
  }

  // 处理队列
  private async processQueue(): Promise<void> {
    if (!this.isProcessing || this.runningExecutions.size >= this.maxConcurrentExecutions) {
      return;
    }

    const task = this.taskQueue.shift();
    if (!task) {
      return;
    }

    try {
      await this.executeTask(task);
    } catch (error) {
      console.error(`执行任务失败 ${task.id}:`, error);
      await this.handleTaskError(task, error as Error);
    }

    await this.updateQueueStatus();
    
    // 继续处理下一个任务
    if (this.taskQueue.length > 0 && this.runningExecutions.size < this.maxConcurrentExecutions) {
      setImmediate(() => this.processQueue());
    }
  }

  // 执行单个任务
  private async executeTask(task: ExecutionTask): Promise<void> {
    const abortController = new AbortController();
    this.runningExecutions.set(task.id, abortController);

    try {
      // 创建执行记录
      const execution = await executionModel.createExecution({
        script_id: task.scriptId,
        connection_id: task.connectionId,
        ...(task.executedBy && { executed_by: task.executedBy })
      });

      // 更新任务ID为执行记录ID
      const executionId = execution.id;
      this.runningExecutions.delete(task.id);
      this.runningExecutions.set(executionId, abortController);

      // 初始化进度
      await this.updateExecutionProgress(executionId, {
        executionId,
        status: 'running',
        progress: 0,
        message: '开始执行',
        startTime: new Date(),
        currentStep: '准备执行环境'
      });

      // 获取脚本内容
      const script = await scriptModel.findById(task.scriptId);
      if (!script || !script.content) {
        throw new Error('脚本不存在或内容为空');
      }

      // 更新进度
      await this.updateExecutionProgress(executionId, {
        executionId,
        status: 'running',
        progress: 10,
        message: '连接数据库',
        currentStep: '建立数据库连接'
      });

      // 执行SQL
      const result = await this.executeSQLWithTimeout(
        task.connectionId,
        script.content,
        task.timeout || this.DEFAULT_TIMEOUT,
        abortController.signal,
        (progress) => this.updateExecutionProgress(executionId, {
          executionId,
          status: 'running',
          progress: 10 + (progress * 0.8), // 10-90%
          currentStep: '执行SQL语句'
        })
      );

      // 更新进度
      await this.updateExecutionProgress(executionId, {
        executionId,
        status: 'running',
        progress: 95,
        message: '保存执行结果',
        currentStep: '处理执行结果'
      });

      // 保存执行结果
      await executionModel.completeExecution(executionId, {
        ...(result.affectedRows !== undefined && { rows_affected: result.affectedRows }),
        ...(result.data && { result_preview: result.data.slice(0, 100) })
      });

      // 完成进度
      await this.updateExecutionProgress(executionId, {
        executionId,
        status: 'completed',
        progress: 100,
        message: '执行完成'
      });

      this.emit('executionCompleted', {
        executionId,
        success: true,
        executionTime: result.executionTime,
        affectedRows: result.affectedRows
      });

    } catch (error: any) {
      const executionId = task.id;
      
      if (error.name === 'AbortError') {
        // 执行被取消
        await this.updateExecutionProgress(executionId, {
          executionId,
          status: 'cancelled',
          progress: 0,
          message: '执行已取消'
        });
      } else {
        // 执行失败
        const execution = await executionModel.findById(executionId);
        if (execution) {
          await executionModel.failExecution(executionId, error.message);
        }

        await this.updateExecutionProgress(executionId, {
          executionId,
          status: 'failed',
          progress: 0,
          message: `执行失败: ${error.message}`
        });

        this.emit('executionFailed', {
          executionId,
          error: error.message
        });
      }
    } finally {
      this.runningExecutions.delete(task.id);
      // 也尝试删除可能的执行记录ID
      const execution = await executionModel.findById(task.id);
      if (execution) {
        this.runningExecutions.delete(execution.id);
      }
    }
  }

  // 带超时的SQL执行
  private async executeSQLWithTimeout(
    connectionId: string,
    sql: string,
    timeout: number,
    abortSignal: AbortSignal,
    progressCallback?: (progress: number) => Promise<void>
  ): Promise<ExecutionResult> {
    const startTime = Date.now();

    return new Promise(async (resolve, reject) => {
      const timeoutId = setTimeout(() => {
        reject(new Error(`执行超时 (${timeout}ms)`));
      }, timeout);

      // 监听取消信号
      abortSignal.addEventListener('abort', () => {
        clearTimeout(timeoutId);
        reject(new Error('执行被取消'));
      });

      try {
        // 模拟进度更新
        if (progressCallback) {
          await progressCallback(0.1);
        }

        // 执行SQL
        const result = await dorisConnectionManager.executeQuery(connectionId, sql);
        
        if (progressCallback) {
          await progressCallback(0.9);
        }

        clearTimeout(timeoutId);
        
        const executionTime = Date.now() - startTime;
        
        resolve({
          executionId: '',
          success: true,
          data: result.rows,
          affectedRows: result.affectedRows || 0,
          executionTime,
          warnings: []
        });

      } catch (error: any) {
        clearTimeout(timeoutId);
        reject(error);
      }
    });
  }

  // 验证执行任务
  private async validateExecutionTask(task: ExecutionTask): Promise<void> {
    // 验证脚本
    const script = await scriptModel.findById(task.scriptId);
    if (!script) {
      throw new Error('脚本不存在');
    }
    if (!script.content || script.content.trim() === '') {
      throw new Error('脚本内容为空');
    }

    // 验证连接
    const connection = await connectionModel.getConnectionById(task.connectionId);
    if (!connection) {
      throw new Error('数据库连接不存在');
    }
    if (!connection.is_active) {
      throw new Error('数据库连接已禁用');
    }

    // 检查是否有相同脚本在相同连接上运行
    const runningExecutions = await executionModel.findAll({
      where: {
        script_id: task.scriptId,
        connection_id: task.connectionId,
        status: 'running'
      }
    });

    if (runningExecutions.length > 0) {
      throw new Error('该脚本在此连接上已有正在运行的执行');
    }
  }

  // 处理任务错误
  private async handleTaskError(task: ExecutionTask, error: Error): Promise<void> {
    task.retryCount = (task.retryCount || 0) + 1;

    if (task.retryCount < (task.maxRetries || this.MAX_RETRIES)) {
      // 重试任务
      task.priority += 1; // 降低优先级
      this.taskQueue.unshift(task); // 添加到队列前面
      this.sortQueue();
      
      console.log(`任务 ${task.id} 执行失败，将进行第 ${task.retryCount} 次重试: ${error.message}`);
      
      this.emit('taskRetry', {
        taskId: task.id,
        retryCount: task.retryCount,
        error: error.message
      });
    } else {
      // 达到最大重试次数，标记为失败
      console.error(`任务 ${task.id} 达到最大重试次数，执行失败: ${error.message}`);
      
      this.emit('taskFailed', {
        taskId: task.id,
        error: error.message,
        retryCount: task.retryCount
      });
    }
  }

  // 按优先级排序队列
  private sortQueue(): void {
    this.taskQueue.sort((a, b) => {
      // 优先级越小越优先，相同优先级按创建时间排序
      if (a.priority !== b.priority) {
        return a.priority - b.priority;
      }
      return a.createdAt.getTime() - b.createdAt.getTime();
    });
  }

  // 更新执行进度
  private async updateExecutionProgress(executionId: string, progress: ExecutionProgress): Promise<void> {
    try {
      const progressKey = `execution:progress:${executionId}`;
      await redisClient.setex(progressKey, 3600, JSON.stringify(progress)); // 1小时过期
      
      this.emit('progressUpdated', progress);
    } catch (error) {
      console.error(`更新执行进度失败 ${executionId}:`, error);
    }
  }

  // 更新队列状态到Redis
  private async updateQueueStatus(): Promise<void> {
    try {
      const queueStatus = {
        queueLength: this.taskQueue.length,
        runningExecutions: this.runningExecutions.size,
        maxConcurrentExecutions: this.maxConcurrentExecutions,
        lastUpdated: new Date()
      };
      
      await redisClient.setex('execution:queue:status', 60, JSON.stringify(queueStatus));
    } catch (error) {
      console.error('更新队列状态失败:', error);
    }
  }

  // 估算任务开始时间
  private estimateStartTime(queuePosition: number): Date {
    const avgExecutionTime = 30000; // 假设平均执行时间30秒
    const estimatedDelay = Math.ceil(queuePosition / this.maxConcurrentExecutions) * avgExecutionTime;
    return new Date(Date.now() + estimatedDelay);
  }

  // 关闭执行引擎
  async shutdown(): Promise<void> {
    this.pauseQueue();
    
    // 取消所有运行中的执行
    const cancelPromises = Array.from(this.runningExecutions.keys()).map(
      executionId => this.cancelExecution(executionId)
    );
    
    await Promise.all(cancelPromises);
    
    // 清空队列
    await this.clearQueue();
    
    this.emit('shutdown');
  }

  // 获取执行统计
  async getExecutionStats(): Promise<{
    totalExecutions: number;
    runningExecutions: number;
    queuedExecutions: number;
    completedToday: number;
    failedToday: number;
    avgExecutionTime: number;
  }> {
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    
    const stats = await executionModel.getExecutionStats({
      start_date: today
    });
    
    return {
      totalExecutions: stats.total_executions,
      runningExecutions: this.runningExecutions.size,
      queuedExecutions: this.taskQueue.length,
      completedToday: stats.successful_executions,
      failedToday: stats.failed_executions,
      avgExecutionTime: stats.avg_duration
    };
  }
}

// 导出单例实例
export const sqlExecutionEngine = SQLExecutionEngine.getInstance();